home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-12-08 | 129.1 KB | 1,939 lines | [TEXT/R*ch] |
- C.S.M.P. Digest Mon, 14 Nov 94 Volume 3 : Issue 67
-
- Today's Topics:
-
- (Q) AppleScript & XCMD's
- Can anyone help me with the Time Manager?
- Dynamic Dialogs?
- How to install your own templates using Macsbug 6.5d6???
- IM: Networking book question
- INIT Writing FAQ [1-3]
- INIT Writing FAQ [2-3]
- INIT Writing FAQ [3-3]
- Linking 68k object files to PPC program
- Network Programming
- Stuck in SyncWait again
- having trouble with AEInteractWithUser & drag manager
-
-
-
- The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
- (pottier@clipper.ens.fr).
-
- The digest is a collection of article threads from the internet newsgroup
- comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
- regularly and want an archive of the discussions. If you don't know what a
- newsgroup is, you probably don't have access to it. Ask your systems
- administrator(s) for details. If you don't have access to news, you may
- still be able to post messages to the group by using a mail server like
- anon.penet.fi (mail help@anon.penet.fi for more information).
-
- Each issue of the digest contains one or more sets of articles (called
- threads), with each set corresponding to a 'discussion' of a particular
- subject. The articles are not edited; all articles included in this digest
- are in their original posted form (as received by our news server at
- nef.ens.fr). Article threads are not added to the digest until the last
- article added to the thread is at least two weeks old (this is to ensure that
- the thread is dead before adding it to the digest). Article threads that
- consist of only one message are generally not included in the digest.
-
- The digest is officially distributed by two means, by email and ftp.
-
- If you want to receive the digest by mail, send email to listserv@ens.fr
- with no subject and one of the following commands as body:
- help Sends you a summary of commands
- subscribe csmp-digest Your Name Adds you to the mailing list
- signoff csmp-digest Removes you from the list
- Once you have subscribed, you will automatically receive each new
- issue as it is created.
-
- The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
- Questions related to the ftp site should be directed to
- scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
- digest are available there.
-
- Also, the digests are available to WAIS users. To search back issues
- with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
- http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
-
-
- -------------------------------------------------------
-
- >From Tom_Brodhurst-Hill@intouch.mpx.com.au (Tom Brodhurst-Hill)
- Subject: (Q) AppleScript & XCMD's
- Date: 31 Oct 1994 19:07:41 GMT
- Organization: MacInTouch BBS
-
- Can anyone tell me whether XCMD's (typically for HyperCard) can be included
- in
- and accessed by a compiled AppleScript application, without running a
- separate HyperCard process?
- Thanks,
- Tom
- please email to tombh@intouch.mpx.com.au
- and post too for others.
- MacInTouch BBS
- info@intouch.mpx.com.au Ph. 61 2 541 1287 BBS. 61 2 541 0799
- *** Sent by FirstClass the graphical email system by SoftArc. Inc. ***
-
- +++++++++++++++++++++++++++
-
- >From lai@apple.com (Ed Lai)
- Date: Mon, 31 Oct 1994 17:20:39 GMT
- Organization: Apple
-
- In article <29224926.900353@intouch.intouch.mpx.com.au>,
- Tom_Brodhurst-Hill@intouch.mpx.com.au (Tom Brodhurst-Hill) wrote:
-
- > Can anyone tell me whether XCMD's (typically for HyperCard) can be included
- in
- > and accessed by a compiled AppleScript application, without running a
- > separate HyperCard process?
- > Thanks,
- > Tom
- > please email to tombh@intouch.mpx.com.au
- > and post too for others.
- > MacInTouch BBS
- > info@intouch.mpx.com.au Ph. 61 2 541 1287 BBS. 61 2 541 0799
- > *** Sent by FirstClass the graphical email system by SoftArc. Inc. ***
-
- It depends on the XCMD, a lot of them can be used, but if they are
- very dependent on HyperCard specifc callback or globals, then they
- cannot.
-
- Try to download the XCMD OSAX.
-
- Generally the place to look for AppleScript related stuff is in
- gaea.kgs.ukans.edu.
-
- If it is just for the XCMD OSAX, you may try ftp.apple.com in
- /pub/lai/osax.
-
- It is an adaptor for AppleScript to use XCMDs. It also comes installed
- with a number of XCMDs by Rinaldi as examples.
-
- In theory you can try it with any other XCMD/XFCNs you got. However to
- do that requires writing certain resources and that is not a easy
- job if you are doing it the first time.
-
- --
- /* Disclaimer: All statments and opinions expressed are my own */
- /* Edmund K. Lai */
- /* Apple Computer, MS303-3A */
- /* 20525 Mariani Ave, */
- /* Cupertino, CA 95014 */
- /* (408)974-6272 */
- zW@h9cOi
-
- ---------------------------
-
- >From anthonym@puree.ugcs.caltech.edu (Anthony Molinaro)
- Subject: Can anyone help me with the Time Manager?
- Date: 21 Oct 1994 08:09:59 GMT
- Organization: California Institute of Technology, Pasadena
-
-
- I worked on this piece of code for a friend using Symatec
- THINK C which turns on the power to a digital I/O board,
- delays for a certain number of ticks, and then turns the
- power off. This was my first time programming on a Macintosh
- and so I had to search a little bit to find out about Delay.
- Now, he tells me he needs a delay time smaller than one tick.
- I know that the time manager can do this but I have been
- unable to get it to work. I guess my confusion arises in the
- type declarations and getting all of the types to match for
- functions InsXTime(), PrimeTime(), and such. The Inside
- Macintosh doesn't have any examples in C and I have not been
- able to accurately port the Pascal functions with the proper
- type settings. My midterms are quickly approaching but I
- promised I would help him out, so any help that anyone could
- give would be .
-
-
-
- /* Here is the original code */
-
- void Play(int note, unsigned long time)
- { long finalTicks;
- short error;
-
- /* turn on power for port,line: portout, lineout */
- error = DIG_Out_Line(4, notes[note].portout, notes[note].line, 1);
- chkerr("DIG_Out_Line",error);
-
- /* if power is on delay */
- if(error == 0)
- Delay(time,&finalTicks);
-
- /* turn off power */
- error = DIG_Out_Line(4, notes[note].portout, notes[note].line, 0);
- chkerr("DIG_Out_Line",error);
- }
-
- /* Here is what I tryed */
- /* global variables */
-
- int note;
- TMTask tblah;
-
- pascal void MyTimeTask(void)
- { DIG_Out_Line(4, notes[note].portout, notes[note].line, 0);
- }
-
- void MyDelay(unsigned long time)
- { tblah.tmAddr = &MyTimeTask();
- tblah.tmWakeUp = 0;
- tblah.tmReserved = 0;
- InsXTime(&tblah);
- PrimeTime(&tblah,time);
- }
-
- This didn't work, and I don't have a lot of time to figure out
- why, so if anyone has any ideas I'm open to them. Thanks in
- advance. Reply through e-mail if possible.
-
- =====================================================================
- Anthony Molinaro
- anthonym@ugcs.caltech.edu
-
-
-
-
- +++++++++++++++++++++++++++
-
- >From Carl R. Osterwald <carl_osterwald@nrel.gov>
- Date: Fri, 21 Oct 1994 17:23:44 GMT
- Organization: National Renewable Energy Laboratory
-
- In article <387t0n$3rr@gap.cco.caltech.edu> Anthony Molinaro,
- anthonym@puree.ugcs.caltech.edu writes:
- >Now, he tells me he needs a delay time smaller than one tick.
- >I know that the time manager can do this but I have been
- >unable to get it to work. I guess my confusion arises in the
- >type declarations and getting all of the types to match for
- >functions InsXTime(), PrimeTime(), and such. The Inside
-
- Here is an example of a Time Manager task:
-
- typedef struct
- {
- TMTask tm_task;
- long A5;
- } time_info;
-
- Initialization:
- timer_rec.tm_task.tmAddr = (TimerProcPtr)&time_task;
- timer_rec.tm_task.tmWakeUp = 0;
- timer_rec.tm_task.tmReserved = 0;
- timer_rec.A5 = SetCurrentA5();
- InsXTime( (QElemPtr)&timer_rec );
- PrimeTime( (QElemPtr)timer_rec, period ); <<-- This starts the task
-
- static void time_task (void)
- {
- time_info *timer_rec;
- long current_A5;
-
- asm
- {
- MOVE.L A1,timer_rec
- MOVE.L A5,current_A5
- };
- SetA5(timer_rec->A5);
- PrimeTime( (QElemPtr)timer_rec, period ); <<-- This restarts
- the task
- SetA5(current_A5);
- } // time_task
-
- You can access your globals between the SetA5 calls. Because the time
- task runs as an interrupt, it is best to minimize processing inside. In
- your case, I would just set a global flag that is polled in the main
- event loop to see if it is tim ; //Restore D0
- SetA0( gOldGNEFilter ); //Put next jGNEFilter in A0
-
- RestoreA4();
-
- asm{
- Unlk A6
- Move.W D0, 4(A7) ;Set Function result on the stack
- JMP (A0) ;Jump to the next jGNEFilter
- }
-
- }
-
- Since a jGNEFilter has access to the actual event record that will be
- returned to the application, the filter can alter the event. The
- most common thing to do is to 'cancel' an event by changing it to a
- null event (Ex. theEvent->what = nullEvent). In this case it should
- also set the value in register D0 to False, or zero.
-
- Here are some additional methods for an extension to get time
- periodically:
-
- If your extension needs more frequent or regular time then can be
- provided by a jGNEFilter then you can install a VBL task or a time
- manager task. Since these run at interrupt time they cannot do
- anything that could move or purge memory. Other methods include
- patching a trap that is called frequently, like SetPort.
-
- A faceless Notification Manager request is another method to get
- time. This is a request that has all the fields in the notification
- record set to NULL except the nmResp field that holds the address of
- your routine to be executed. Your notification response routine will
- be called soon and will be able to move memory. If necessary the
- routine can reinstall itself. This technique is useful for tasks
- that need to be executed once or intermittently. For those tasks
- that need to be executed regularly use one of the other techniques.
-
- You could of course have a faceless NM request that is installed by a
- VBL task or a time manager task.
-
- Use of a faceless background application in concert with an extension
- is yet another method to get time. The fba would do its work on its
- null events.
-
- --
- [11] How should an INIT manage memory?
-
- In general, at INIT time extensions will want to allocate memory in
- the system heap. If you are allocating pointers or handles, use the
- SYS variants, like NewHandleSys() and NewPtrSys(). It is a common
- error to forget this and then to wonder why the INIT crashes. If you
- call NewHandle at INIT time, the handle will be allocated in the
- temporary heap allocated for your extension. If your INIT attempts
- to use it after INIT time the temporary heap will be long gone, along
- with any handles or pointers that had been allocated in it. Any
- attempt to use handles or pointers that no longer exist are
- predictably unpredictable :-)
-
- NewHandle and NewPtr will allocate their memory blocks in the system
- heap if the zone has been set to the system heap, as shown in the
- next paragraph.
-
- If you need to read in resources you can ensure that they go into the
- system heap with something like the following code:
-
- THz saveZone = GetZone();
- SetZone( SystemZone() );
- //read in resources
- SetZone( saveZone );
-
- You will of course need to detach the resources if they need to
- remain in memory after your extension exits. The resource file
- containing your extension will be closed when your extension exits.
-
- If you need to read resources into memory after INIT time you need to
- decide which heap they should go into, either the application heap or
- the system heap. It's a bit hard to make a specific recommendation
- on this but if the resource is something that the application is
- expecting to be read in then it should go into the application heap.
- This would include things like WIND resources in a trap patch to
- GetNewWindow(). The problem of course is that the application heap
- may not have enough room. However, if the resources are private to
- the extension then they should go into the system heap.
-
- It should go without saying that you should always check the error
- codes on memory allocating calls and resource manager calls. If your
- extension is doing something in response to a user action, say making
- a network connection, then it is appropriate to report such errors.
- In many cases however, your extension will simply do nothing in the
- case of out of memory errors or missing resource errors. It is best
- to attempt to allocate all of these things at INIT time and if
- unsuccessful to bail out then.
-
- As mentioned above, MoveHHi doesn't work in the system heap. If you
- intend to allocate a handle that will remain locked for extended
- periods, then call ResrvMem before allocating and locking the handle.
- This will place the handle low in the system heap and help to prevent
- heap fragmentation.
-
- Many toolbox calls are documented as not moving or purging memory and
- as being safe to call at interrupt time. If you are patching one of
- these traps then you must preserve this property. You are guaranteed
- to cause other software to crash if you don't, and your users will
- hate you (once they figure out that it's you). Be aware that the
- only memory manager routine safe to call under these circumstances is
- BlockMove. Also be aware that it is unsafe to access an unlocked
- handle at interrupt time. It is possible that the memory manager is
- in the midst of moving it from one place to another in the heap, and
- the master pointer may not be updated yet.
-
- --
- [12] How do I get my INIT to turn itself off?
-
- An extension might want to turn itself off at INIT time based on its
- preferences setting, or based on a key being pressed or the mouse
- button being pressed, or due to an error during initialization.
- Extensions usually show an icon with a red X through it in this case.
- An extension might also want to turn itself off temporarily after
- INIT time in response to its Control Panel. For instance GateKeeper
- has an on/off switch that turns off virus checking for a set time.
-
- The strategy for temporarily turning off an extension is simply to
- set a global flag and to check it from within the trap patches or
- other parts of the extension. If the flag is off then the trap patch
- simply executes the previous trap. It is generally unsafe to unpatch
- or patch traps after INIT time from an extension. The reason for
- this is that if another extension patches the same trap after you
- have, then it will be jumping to your patch when it has completed its
- work. If you have removed your patch then this calling chain will be
- disrupted and bad things will happen. Also, the Finder patches
- various traps when it loads, which is after INIT time. Disrupting
- those patches would be a very bad thing.
-
- If an extension determines at INIT time that it isn't going to stay
- around then it shouldn't call DetachResource on itself. It's best
- that your extension determine that anything it's dependent on, such
- as resources, specific system Managers, and sufficient memory, are
- present *before* it starts to patch traps and install drivers,
- jGNEFilters and so on. It would be a very bad idea for an extension
- to not detach itself after it had already patched a trap if the trap
- patch resided in the extension.
-
- Many extensions use a particular key press as a signal to indicate
- that the user wants them not to run. Of course the system uses the
- shift key as a signal not to turn on any extensions so you can't use
- that. Some extensions use the option or command keys for this
- purpose. The problem with using those keys is that every time I
- rebuild the desktop those extensions are needlessly inactivated. I
- recommend that the space bar be used for this purpose. Here's some
- sample code:
-
- Boolean
- SpaceBarIsDown(void)
- {
- KeyMap theKeys;
-
- GetKeys( theKeys );
-
- if ( theKeys[1] & 0x00000200 )//Check for spacebar
- return TRUE;
- else
- return FALSE;
-
- }
-
- --
- [13] How do I get my INIT to show it's icon like all the other cool
- inits do?
-
- This is easy. There is code available that does this for you. Get a
- package written by Jim Walker called ShowIcon7 at:
- ftp://mac.archive.umich.edu/mac/development/source/showicon7.sit.hqx
-
- You use it essentially as a plug-in. Just pass in the icon's
- resource ID and it does everything for you. It also shows how to set
- up an A5 world in an extension. You might also take a look at Dair
- Grant's Extension shell package. This one shows how to do animated
- icons.
-
- If your extension decides that it can't install itself then it passes
- the resource ID of an icon that has a red X through it to the
- showicon7 code resource.
-
- Some extensions include the ShowIcon code within their own code
- resources. This code is only about 1K but it seems pointless to me
- for this code to sit in the system heap when it doesn't have to be.
- Use it as a plug-in for your extensions.
-
- --
- [14] How do I show a dialog from my INIT?
-
- First of all, I hate windows of any kind during the startup process.
- If all you want to do is show an alert then use the Notification
- Manager. Your alert will show up when the Finder starts but the user
- will see it and will get whatever message you need to send.
-
- The problem I have with windows at INIT time is that they slow down
- this process and require user interactivity in a process that
- shouldn't do so. Consider the computer that is on 24 hours a day
- doing something important unattended. The power goes off and when it
- comes back on the machine reboots. The user returns several hours
- later to find that the machine is still in the middle of its startup
- because your alert is waiting for a response. Consider also the
- hapless INIT writer who has to reboot his machine 20 times a day.
- Your INIT will not last long on my, um, his machine.
-
- One additional annoyance is that you need to call InitWindows to show
- your window and this erases all the nice INIT icons on the screen. I
- hate that.
-
- Here are a few possible alternatives.
-
- * Play a sound or use the Speech Manager to communicate the
- information.
-
- * Show a different icon during startup to indicate an error. An icon
- with a red X through it is one way to do this. You could also use
- animated icons.
-
- * If you must put up an alert then use a timer so that the alert goes
- away by itself, even if the OK button isn't clicked.
-
- * If you need to interact with the user to get some information, say
- a password for a network connection, then do this once and save the
- results in a preferences file. Provide a Control Panel to change the
- information. Think of Control Panels as the interface for
- extensions.
-
- * Store descriptions of any errors that occur in a preferences file.
- Have the Control Panel display this information. Remember to clear
- this information on each restart and to indicate to the user by sound
- or icon that an error has occurred.
-
- * If you need to communicate error information to the user after INIT
- time then you should definitely use the Notification Manager. For
- example, MacSLIP uses the NM to show an alert indicating that the
- carrier has been lost.
-
- If you still want to show a dialog at INIT time then you need to set
- up an A5 world first. The ShowIcon7 code mentioned above shows how
- to do this. Also see the Tech Note 'Stand-Alone Code' (#256) for an
- explanation and sample code for this and 'Giving the (Desk)Hook to
- INITs' (247) discusses a bug that can appear when showing windows
- from extensions.
- ftp://ftp.apple.com/dts/mac/tn/operating.system.os/os-02-deskhook-
- and-init.hqx
-
- If you do use the Notification Manager from an extension to indicate
- that the extension couldn't load you should use a self-disposing
- Notification request. There are several strategies for doing this.
- I have some code samples for this that will be (have been?) posted to
- alt.sources.mac soon.
-
- --
- [15] How do I maintain compatibility with future systems?
-
- This is tough, and the short answer is that you probably don't.
- You'll notice that Apple comes out with new versions of its
- extensions with each revision of the system. Apple's extensions also
- eventually disappear as their functionality is rolled into the
- system. In all likelihood you'll have to come out with new versions
- of your extensions as new versions of the system come out as well.
-
- Having said all that, there are things you can do to minimize this
- problem. Here are a few suggestions:
-
- * Minimize your reliance on undocumented features of the system.
-
- * Minimize your reliance on low memory globals. Use the Universal
- Header access 'functions' for accessing the low memory globals if
- necessary.
-
- * Use system features like Gestalt, the Process Manager, and the
- Notification Manager to get information about the system, and to
- communicate with the user.
-
- * Try to patch as few traps as possible and use non-patching methods
- whenever possible (e.g., use a jGNEFilter instead of patching
- WaitNextEvent; the filter is more likely to remain compatible than
- your patch).
-
- * Don't use self-modifying code. Self-modifying code changes the
- instructions from what they were compiled as, to something else, at
- run-time. The classic example is to change the address in a JMP
- instruction at run-time so that it jumps to the address of the
- previous trap. This may seem faster than using a global variable but
- it is only slightly faster. It is harder to write, debug, and
- maintain self-modifying code, and it is definitely more likely to
- break with new system releases. If you do use self-modifying code,
- remember to flush the cache. See the tech note 'Cache As Cache Can'
- (#261) for more information on that subject.
-
- * Use the Universal Headers for writing your extensions. This will
- help to ease the transition when it comes.
-
- --
- [16] Any tips for INIT writing?
-
- You may not want your INIT to actually do anything until after INIT
- time. You can find the end of INIT time if you have a jGNEFilter
- installed when the first null event occurs. The Notification Manager
- doesn't usually start processing requests until INIT time is over so
- posting a faceless notification request is another method to find the
- end of INIT time (probably the best if you don't need a jGNEFilter
- for something else). You can also patch Launch to find the end of
- INIT time but this is trickier.
-
- Unfortunately some extension writers do put up windows during INIT
- time. Because of this it's possible that events will occur before
- INIT time is over. To fail-safe the above approaches you also need
- to check for the presence of the Process Manager with a Gestalt call.
- The Process Manager isn't available until after INIT time. If
- Gestalt reports that the Process Manager is not available then you
- need to reinstall your NM request, or simply wait for another event
- to be reported to your jGNEFilter when the Process Manager is
- available.
-
- Here are some utility routines that can reduce the need for 68K
- assembler in your extensions:
-
- pascal void SetA0( void* ) = { 0x205F };
- pascal void SetA1( void* ) = { 0x225F };
- void * GetA0( void ) = { 0x2008 };
- void * GetA7( void ) = { 0x200F };
-
-
- - -------------------------------------------------------------------
-
- Trap Patches:
-
- --
- [17] What exactly is a trap patch?
-
- A trap patch is a method for changing the functionality of a trap.
- The addresses of all the traps are maintained in the two trap
- dispatch tables. By using the routine NSetTrapAddress and friends
- you can change the address of a particular trap to code that you
- provide. When this is done at INIT time, all calls to the patched
- trap from all applications will go to your code, which in most cases
- will do something and then call through the existing trap in the
- ROMs. Be warned that the Finder patches some traps when it starts up
- in a way that prevents previously-installed patches from executing.
-
- I recommend that you read the descriptions of the trap dispatch
- mechanism in the 'Using Assembly Language' chapters in IM I and IV
- and also in the 'Trap Manager' chapter in NIM Operating System
- Utilities.
-
- Traps come in several types based on their parameter passing
- conventions. Most toolbox traps use pascal calling conventions,
- which means that all parameters are passed on the stack and the
- return value, if any, is placed on the stack.
-
- Some traps use register-based calling conventions. In these traps
- the parameters are passed in registers and the return value is
- returned in a register, usually D0. For example all the Memory
- Manager traps are register-based and the File Manager traps are also
- register-based.
-
- Some traps are selector-based. There are only so many spots in the
- trap-dispatch tables. In order to preserve space in these tables
- selector-based traps have been developed. In these traps a single
- trap serves as the front end for a number of system routines. The
- parameters of these traps are passed in the usual manner, either on
- the stack or in registers, and a selector is also passed, usually in
- a register. When the trap is called it checks the selector and then
- dispatches to the appropriate routine. Patching each of these types
- of traps involves different mechanisms. We'll look at samples of
- each one.
-
- Patching traps on the PowerMac is a bit different than on the 68K
- Macs. Most of the discussion here is aimed at patching traps on the
- 68K Macs. Hopefully I'll learn some more about this subject soon and
- there will be some better info here on patching traps on the
- PowerMac.
-
- --
- [18] What's the difference between a head patch and a tail patch?
-
- It is most common to add some functionality to a trap when patching
- it rather than just replacing the existing trap. For instance I've
- written an extension that speaks the text in alerts by using the
- Speech Manager. This works by patching Alert and friends. When
- Alert is called the patch gets the text that appears in the alert and
- passes it to the Speech Manager. The patch then calls the existing
- Alert trap that is in the ROMs. A patch that works in this way is
- called a head patch; it does its business and then it calls the
- previous trap.
-
- A tail patch is a bit different. A virus-checking program might want
- to patch GetResource and then examine the resource that was read in
- to see if it contains a virus. In order to do this the patch must
- first call the existing trap and then do its processing, and finally
- return to the application. This is a tail patch because some
- processing occurs after the existing trap is called. In order for a
- patch to be a head patch you must use a jmp instruction to jump to
- the previous trap. If you use a jsr or a C function pointer to jump
- to the previous trap you have a tail patch.
-
- The reason that this head and tail patch business has been so
- important in the past is because of an Apple invention called the
- come-from patch. Patches were invented, of course, so that Apple
- could fix bugs in the ROMs and could update the routines in the ROMs
- with software. This is why you can run system 7 on a Mac Plus, whose
- ROMs are obviously missing most of the additions made to the toolbox
- in recent years.
-
- Certain ROM routines are particularly large so it is inconvenient to
- patch them if they have bugs in them. To get around this problem the
- Apple programmers searched for smaller routines that are called from
- the large buggy routines and placed patches in the smaller routines.
- These patches check the return address on the stack. If it is the
- address of the buggy routine then a fix is applied. If not then they
- just go on as usual. The patches to these smaller routines are known
- as come-from patches. If you tail patch one of these and then call
- the existing come-from patch, the return address on the stack will be
- in your patch and not the buggy routine that called you. In this
- case the come-from patch will not apply its fix and your system will
- crash.
-
- The good news is that as of system 7 it is safe to apply tail
- patches. The come-from patches still exist in system software, but
- NGetTrapAddress has been modified to return an address that is safe
- to use when applying tail-patches. However, if you wish your
- extension to run in System 6 then tail-patches are not allowed. This
- is documented in the Trap Manager chapter in NIM: OS Utilities.
-
- If you absolutely positively need a tail patch in System 6 then the
- following logic may apply: (Just don't tell anyone that I told you
- this :-) Apple is not releasing any new versions of System 6 so no
- new come-from patches will be forthcoming for System 6. If you do
- careful testing of the traps you wish to tail-patch you will probably
- be OK. In general traps not called from the ROMs, like Alert and
- MenuKey, will not contain come-from patches.
-
- One final thing: In system 7 it is safe to apply tail-patches to all
- traps except FrontWindow.
-
- --
- [19] How do I patch a trap?
-
- Here is some sample code for a head patch of Alert, a stack-based
- trap:
-
- TrapPtr gOldAlertTrapAddress;
-
- /****InstallPatch***************************************************/
-
- void
- InstallPatch (void)
- {
- gOldAlertTrapAddress = GetToolTrapAddress( _Alert );
- SetToolTrapAddress( (long) AlertPatch, _Alert );
- }
-
- /****AlertPatch***************************************************/
-
- pascal void
- AlertPatch( short alertID, ProcPtr filterProcPtr )
- {
- SetUpA4();
-
- MyAlert( alertID) ; //Do our thing
-
- //store the correct alert addr
- //in A0 while we can still access globals via A4
-
- asm { move.l gOldAlertTrapAddress, A0 }
-
- RestoreA4();
-
- asm {
- unlk A6 //match the link generated by C
- jmp (A0) //jump to _Alert
- }
- }
-
- There are a number of details to note here. This patch is of course
- part of a code resource that is loaded at INIT time and detached as
- described in an earlier section. The routine InstallPatch must be
- called at INIT time.
-
- The routines GetToolTrapAddress and SetToolTrapAddress allow you to
- get and set the addresses of Tool Traps. The similar routines
- GetOSTrapAddress and SetOSTrapAddress allow you to manipulate the
- addresses of OS traps. The routines NGetTrapAddress and
- NSetTrapAddress allow you to manipulate the addresses of either,
- although they call glue code. I recommend that you use the
- GetXTrapAddress and SetXTrapAddress calls. There are two obsolete
- calls: GetTrapAddress and SetTrapAddress. Don't use them.
-
- The prototype for this patch is declared as 'pascal void' while the
- prototype for Alert is 'pascal short'. Because this is a head patch
- it will not be returning a result; the result will be returned from
- the real Alert trap. The pascal keyword is used to indicate pascal
- calling conventions. It is not strictly required in all cases but
- does no harm.
-
- The Think C routines SetUpA4 and RestoreA4 are called to allow access
- to global variables by A4 addressing. In this case
- gOldAlertTrapAddress is the only global variable we are addressing,
- unless any are used inside MyAlert. Note that this variable is moved
- to A0 while access to global variables is still available. In some
- cases one might move a global variable to a local variable, which
- doesn't rely on A4 addressing. A4 could then be restored and the old
- trap address could be loaded into A0 later in the code.
-
- Because there is a parameter list the compiler generates a Link A6
- instruction at the start of this function. In order to restore the
- stack a matching Unlk A6 must be placed at the end of the function.
- Since we are exiting by the jmp (A0) we must insert the Unlk A6
- ourselves. The compiler does generate an Unlk A6 and an RTS at the
- end of this function, but they will never be executed. The presence
- of the Link A6 instruction is dependent on the particular compiler
- you use and on its rules for generating a stack frame. It is a good
- idea to disassemble the code for your trap patches to see whether a
- stack frame has been generated in order to determine if you need to
- insert the Unlk A6 instruction. If you don't match the Link A6 with
- an Unlk A6 the stack will be screwed up.
-
- It is essential that the stack look exactly the same on exit from a
- head patch as it does on entry. If not you will surely crash. (If
- you had good reason you could modify the value of a parameter on the
- stack, but that's another story.) This patch saves and restores A4
- but does modify A0 and A1 (SetUpA4 uses A1). In general, with head
- patches of stack-based traps you can modify A0, A1, D0, D1, and D2,
- but not any other registers. You may need to look at the
- disassembled code to be sure that all your registers are properly
- saved and restored.
-
- The design of the patch as shown here, with the patch code calling a
- separate function to perform the actual functionality of the patch is
- a good design to follow with all but the simplest of patches.
-
- You might think that you need to call StripAddress on the address of
- the patch routine before passing this address to SetToolTrapAddress.
- This is not necessary unless the address is actually a handle. If
- you were to load a code resource and pass its entry point to
- SetToolTrapAddress then it would need to be stripped.
-
- --
- Brian Stern :-{)}
- Toolbox commando and Menu bard
- Jaeger@fquest.com
-
- ---------------------------
-
- >From Jaeger@fquest.com (Brian Stern)
- Subject: INIT Writing FAQ [3-3]
- Date: 28 Oct 1994 00:44:27 GMT
- Organization: The University of Texas at Austin, Austin, Texas
-
- --
- [20] How do I patch a register-based trap?
-
- Here is the code for a sample register-based trap patch:
-
- TrapPtr gMountVolAddress;
-
- /****InstallPatch**************************************************/
-
- void
- InstallPatch(void)
- {
- gMountVolAddress = GetOSTrapAddress( _MountVol );
- SetOSTrapAddress( (long) MountVolPatch, _MountVol );
- }
-
- /****MountVolPatch**************************************************
-
- This is a register-based trap that has A0 set to point to its
- parameter
- block on entry. The prototype for MountVol is:
-
- pascal OSErr PBMountVol( ParmBlkPtr paramBlock )
-
- This patch beeps when a floppy or CD-ROM is inserted or when a
- harddrive is mounted by the Finder.
-
- *******************************************************************/
-
- pascal void
- MountVolPatch(void)
- {
- //Save some registers
- //Save A0 since it's trashed by SetUpA4
- //D1 contains the trap word
-
- asm { movem.l a0/d0-d1, -(sp) }
-
- SetUpA4(); //Allow access to global variables
-
- SysBeep( 5 ); //The guts of our head patch
-
- //store the correct MountVol addr
- //in A1 while we can still access globals via A4
- asm { move.l gMountVolAddress, A1 }
-
- RestoreA4(); //Restore previous value in A4
-
- asm { //Restore the registers
- movem.l (sp)+, a0/d0-d1
- jmp (A1) //jump to _MountVol
- }
-
- }
-
- This head patch is similar in structure to the patch to Alert with a
- few differences. The prototype uses no parameters and has no return
- value. The single parameter is passed through A0. This patch doesn't
- do anything with this value but it could be moved to a local variable
- and then used to reference the fields in the parameter block if
- desired. Access to global variables is by the same A4 mechanism as
- in the Alert patch. Note that _MountVol is an OS trap so
- GetOSTrapAddress and SetOSTrapAddress are used to set up the patch.
-
- Since A0 is used to pass the parameter to this trap we jump to the
- real _MountVol trap through A1.
-
- Obviously A0 must be saved and restored in this patch. OS traps
- expect to find the trap word in D1 so it must be saved and restored
- as well. Three registers, A0, D0, and D1, are saved onto the stack
- with the movem instruction, and restored at the end of the patch.
-
- Think C doesn't generate a 'Link A6' at the start of this function
- because there are no parameters and no local variables. Because of
- this no 'Unlk A6' is needed at the end of the function.
-
- --
- [21] Can you show me an example tail patch?
-
- Here is another example of a patch to a register-based trap. This
- sample is a tail patch and is dependent on the CodeWarrior
- environment. Because CW allows you to specify that parameters are
- passed in registers this trap patch requires no assembly.
-
- extern pascal OSErr (*Old_MountVol)( ParmBlkPtr pb : __A0 ) : __D0;
-
- pascal OSErr My_MountVol( ParmBlkPtr pb : __A0 ) : __D0
- {
- OSErr err;
- long saveA4 = SetCurrentA4();
-
- err = Old_MountVol( pb );
- DoSomthingFunc();
-
- SetA4( saveA4 );
- return err;
- }
-
- --
- [22] How do I patch a selector-based trap?
-
- Here is a sample patch to PrGlue. This trap is the front end for all
- the Printing Manager routines. Its selector is pushed on the stack
-
- typedef struct
- {
- long Selector;
- THPrint hPrint;
- } PrJobDialogStack;
-
- TrapPtr PrGlueAddress;
-
- /****InstallPatch****************************************************
- /
-
- void
- InstallPatch(void)
- {
- PrGlueAddress = GetToolTrapAddress( _PrGlue );
- SetToolTrapAddress( (long) PrGluePatch, _PrGlue );
- }
-
- /****PrGluePatch****************************************************
-
- This is a stack-based trap with a long word selector also pushed
- onto the stack. On entry the selector is at 4(A7). The return
- address is at 0(A7). After the 'Link A6' the selector is at 12(A7).
-
- *******************************************************************/
-
- #define kSelectorOffset 12
- #define kPrJobDialogSelector 0x32040488
-
- pascal void
- PrGluePatch(void)
- {
- PrJobDialogStack *StackPtr;
-
- //Get address of the stack frame
- //and save it in a local variable
-
- asm {
- lea kSelectorOffset(A7), A0
- move.l A0, StackPtr
- }
-
- SetUpA4(); //Allow access to global variables
-
- //Check the selector
- if ( StackPtr->Selector == kPrJobDialogSelector )
- {
- SysBeep( 5 );
-
- //Pass hPrint to our function to do something
- DoSomethingFunc( StackPtr->hPrint );
- }
-
- //Store the correct PrGlue addr
- //in A0 while can still access globals via A4
- asm { move.l PrGlueAddress, A0 }
-
- RestoreA4(); //Restore previous value in A4
-
- asm {
- unlk A6 //match C's Link A6
- jmp (A0) //jump to _PrGlue
- }
-
- }
-
- In order to access the selector and the parameters for PrGlue we use
- a pointer to a struct. Once the pointer is initialized correctly we
- can access the selector and any parameters from C easily.
-
- According to NIM: PPC System Software it is not safe to patch
- selector-based traps with PPC native code. All patches of selector-
- based traps on the PowerMac should be written in 68K code.
-
- --
- [23] How do I patch a trap on the PPC?
-
- See NIM 'PowerPC System Software' for a more complete discussion.
- There is also a new book by Tom Thomson called 'Power Macintosh
- Programming Starter Kit' that has examples of how to patch traps on
- the PowerMac.
-
- Patching traps on the PowerMac is similar to patching on the 68K
- architecture. Of course you must generate a UniversalProcPtr for
- each of your patches in the system heap, and these are then passed to
- the SetXTrapAddress routines. Since code fragments have their own
- globals the use of A4 or A5-based mechanisms for accessing global
- variables isn't needed. In order to call the previous trap you need
- to call CallUniversalProc or CallOSTrapUniversalProc and return its
- result from your patch. As a result all patches on the PowerMac are
- tail patches.
-
- You may find an application called 'Traps Check' useful. This app
- supplies a report about all the traps on a Powermac, indicating
- whether each trap is emulated or native. Another way to do this is
- to drop into MacsBug and disassemble from the address of the trap
- you're interested in (e.g., 'il CopyBits' ). For traps that are
- native you'll see a routine descriptor that begins with the
- MixedModeMagic trap (AAFE). This of course won't tell you if the trap
- has been patched. You can identify a patch by whether it's in RAM or
- ROM, from its address. Determining whether a patched trap is PPC
- native or not may take some additioinal sleuthing. You can find Traps
- Check at: ftp://sumex-aim.stanford.edu/info-mac/dev/traps-check-
- 10.hqx
-
- Here is a sample PowerMac trap patch for GetResource:
-
- UniversalProcPtr gGetResourceUPP;
- UniversalProcPtr gGetResourcePatchUPP;
-
- /****InstallPatch**************************************************/
-
- void
- InstallPatch(void)
- {
- gGetResourceUPP = GetToolTrapAddress( _GetResource );
-
- gGetResourcePatchUPP =
- NewRoutineDescriptor( (ProcPtr) GetResourcePatch,
- kPascalStackBased, GetCurrentISA() );
-
- SetToolTrapAddress( gGetResourcePatchUPP, _GetResource );
-
- }
-
-
- /****GetResourcePatch*********************************************/
-
- Handle
- GetResourcePatch( ResType theType, short theID )
- {
- Handle result;
-
- //We don't need no 'DUMB' resources
- if ( theType == 'DUMB' )
- result = NULL;
- else
- result = (Handle) CallUniversalProc( gGetResourceUPP,
- kGetResourceProcInfo, theType, theID );
-
- return result;
-
- }
-
- --
- [24] Can I write a fat trap?
-
- //Under construction
-
- --
- [25] Tips?
-
- If your patch isn't called you may have guessed wrong on whether it's
- a ToolTrap or an OSTrap. The high bit of the second byte of the trap
- word is set for ToolTraps. The following function can be used to get
- the correct trap address for both ToolTraps and OSTraps.
-
- pascal void * GetCurrentTrapAddress( unsigned short trapWord )
- {
- if ( trapWord & 0x0800 )
- return GetToolTrapAddress ( trapWord & 0x07FF );
- else
- return GetOSTrapAddress ( trapWord & 0x07FF );
- }
-
-
- If the machine crashes after leaving your patch you have probably
- munged the stack or not saved and restored all the registers that you
- must.
-
- The Finder patches a number of traps when it loads in a way that
- prevents earlier trap patches from functioning. If your patch
- doesn't appear to be called it may be one of these patches.
-
- --
- [26] What other sources of information are available?
-
- Knaster 'How to Write Macintosh Software'
- Knaster and Rollin, 'Macintosh Programming Secrets'. These books on
- Mac programming has some excellent info on trap patching.
-
- Tom Thomson 'Power Macintosh Programming Starter Kit' This book has
- some example code for writing trap patches and extensions on the
- PowerMac.
-
- The Extension Shell package at:
- ftp://sumex-aim.stanford.edu/info-mac/dev/src/extension-shell-13.hqx
- Dair's email address has changed to: dair.grant@ucl.ac.uk.
-
- Usenet Macintosh Programmers Guide
- ftp://sumex-aim.stanford.edu/info-mac/dev/info/usenet-mac-prog-guide-
- msw.hqx
-
- All of the Apple Tech Notes have been made available on Apple's web
- server: http://www.info.apple.com/dev/technotes/Main.html
-
- --
- Brian Stern :-{)}
- Toolbox commando and Menu bard
- Jaeger@fquest.com
-
- ---------------------------
-
- >From shawnl@andyne.on.ca (Dave Charlesworth)
- Subject: Linking 68k object files to PPC program
- Date: Thu, 27 Oct 1994 19:26:03 GMT
- Organization: Andyne Computing
-
- I want to link some third party code to a PowerPC program. Can someone
- point me to documentation on how to make this work?
-
- I don't have source for the third party stuff. I'm using MPW (ETO 15)
- cross- platform tools (PPCLink, PPCC), and have the Inside Mac volume
- "PowerPC System Software". I haven't been able to find anything in it
- or in the ETO documentation, but it must be somewhere!
-
- Thanks.
-
- Shawn Leclaire
-
- +++++++++++++++++++++++++++
-
- >From zellers@pokey.basilsoft.com (Steve Zellers)
- Date: Fri, 28 Oct 1994 20:52:49 -0800
- Organization: BasilSoft, Inc.
-
- In article <CyCJBF.Ms4@andyne.on.ca>, shawnl@andyne.on.ca (Dave
- Charlesworth) wrote:
-
- > I want to link some third party code to a PowerPC program. Can someone
- > point me to documentation on how to make this work?
-
- Assuming you mean that the third party code is 68k, you can't. You'll
- have to write a stub code resource that re-exports all the symbols you
- need through a paramblock as some sort using route descriptors.
-
- --smz
-
- +++++++++++++++++++++++++++
-
- >From wdh@fresh.com (Bill Hofmann)
- Date: Sat, 29 Oct 1994 18:27:36 GMT
- Organization: Fresh Software
-
- In article <CyCJBF.Ms4@andyne.on.ca>, shawnl@andyne.on.ca (Dave
- Charlesworth) wrote:
-
- > I want to link some third party code to a PowerPC program. Can someone
- > point me to documentation on how to make this work?
- >
- > I don't have source for the third party stuff. I'm using MPW (ETO 15)
- > cross- platform tools (PPCLink, PPCC), and have the Inside Mac volume
- > "PowerPC System Software". I haven't been able to find anything in it
- > or in the ETO documentation, but it must be somewhere!
- >
- Nope, not really. Maybe some of the MacTech articles have mentioned it.
- But what you have to do is:
- * find out which routines *you* call in the library
- * write some 68k code that wraps the library in a way that you can
- call it: either use a selector-based approach (ie, if message==1,
- call function 1, etc) or make a routine that returns a table of
- procptrs
- * compile/link the wrapper with the library
- * create proc infos and stub code to call your 68k wrapper in your
- PowerPC program
- * debug :->
-
- Or, yell at the third party until they produce a PowerPC version (shared
- library, or whatever).
-
- -Bill
-
- --
- Bill Hofmann wdh@fresh.com
- Fresh Software and Instructional Design voice: +1 510 524 0852
- 1640 San Pablo Ave #C, Berkeley CA 94702 USA fax: +1 510 524 0853
-
- ---------------------------
-
- >From rjkmehta@bu.edu (Ravi Mehta)
- Subject: Network Programming
- Date: 19 Oct 1994 16:20:21 GMT
- Organization: Boston University
-
- I want to write some networkable software, but am completely new to network
- programming. Besdies IM: Networking ( which I will pickup ) is there
- anything else that would help? Will IM: Networking discuss programming
- for BOTH AppleTalk and Ethernet? If not, what would be a good
- source for learning how to write Ethernet and AppleTalk compatible software.
-
- Thanks in advance.
-
- Ravi J. K. Mehta
- Terminal Sunset Software
-
-
- +++++++++++++++++++++++++++
-
- >From andym96@aol.com (AndyM96)
- Date: 20 Oct 1994 01:13:05 -0400
- Organization: America Online, Inc. (1-800-827-6364)
-
- In article <383h05$a37@news.bu.edu>, rjkmehta@bu.edu (Ravi Mehta) writes:
-
- <<
- Will IM: Networking discuss programming
- for BOTH AppleTalk and Ethernet? If not, what would be a good
- source for learning how to write Ethernet and AppleTalk compatible
- software.>>
- yes, IM networking discusses how to do that. Also, a good book is
- "Programming with AppleTalk" by Michael Peirce -code samples are in
- Pascal, though, but it is a thorough and detailed description of how
- AppleTalk protocols work & how to use 'em.
- BTW, if you dicover a code sample how to write a requester-responder pair
- using ATP in C, <<PLEASE>> e-mail me @ andym96@aol.com -I've been trying
- to get this info for a couple of weeks now with no avail.
- Andy
-
- +++++++++++++++++++++++++++
-
- >From ntuck@muddcs.cs.hmc.edu (Nathan D. Tuck)
- Date: 20 Oct 1994 20:02:38 GMT
- Organization: Harvey Mudd College, Claremont CA
-
-
- >In article <383h05$a37@news.bu.edu>, rjkmehta@bu.edu (Ravi Mehta) writes:
- >
-
- >Will IM: Networking discuss programming
- >for BOTH AppleTalk and Ethernet? If not, what would be a good
- >source for learning how to write Ethernet and AppleTalk compatible
- >software.>>
-
- For both AppleTalk and Ethernet? AppleTalk is a software protocol while
- Ethernet is the physical format that AppleTalk runs over. If you mean
- LocalTalk and Ethernet, the two should be equivalent so far as ATP
- API's are concerned. If you mean to run transparantly over different
- protocol stacks such as ATP and IPX/SPX or TCP/IP, that is another
- question entirely.
-
- Nate
- ntuck@hmc.edu
-
-
-
- +++++++++++++++++++++++++++
-
- >From Yorick_Ph*nix,MacTel_Iconex@metro.mactel.org (Yorick
- Ph*nix,MacTel_Iconex)
- Date: 29 Oct 1994 02:48:38 GMT
- Organization: MacTel Metro BBS, London, England.
-
- Ravi
-
- > I want to write some networkable software, but am completely new to
- > network programming. Besdies IM: Networking ( which I will pickup )
- > is there anything else that would help?
-
- There is a very good book called something like Introduction to AppleTalk
- Programming - I have a copy at the office and I learnt all my Network
- Programming from it. It is possibly published by Addison-Wesley and is one in
- a series where Scott Knaster is the Series Editor.
-
- AppleTalk programming is what you should be doing (ATP, NBP, ADSP, PAP, etc)
- whereas LocalTalk and EtherNet are the phsyical mediums over which the
- network data travels - you shouldnt need to get involved at this level or
- even know which phsyical medium your program is dealing with.
-
- Yorick
-
- - sent via an evaluation copy of BulkRate (unregistered).
-
- --
- ****************************************************************************
- MacTel Metro - Europes largest Mac specific BBS
- The views expressed in this posting those of the individual author only.
- Send mail to this user at either :-
- INTERNET:User_Name@metro.mactel.org [use underline] between first
- FIDONET:User.Name@f202.n254.z2.fidonet.org [use fullstop ] & last names
- ****************************************************************************
-
- ---------------------------
-
- >From walkerj@math.scarolina.edu (James W. Walker)
- Subject: Stuck in SyncWait again
- Date: Sat, 15 Oct 1994 21:39:18 -0500
- Organization: Dept. of Mathematics, Univ. of South Carolina
-
- When an application freezes, dropping into MacsBug often reveals that it
- is stuck in SyncWait. When that happens, typing es to MacsBug or using
- force-quit does nothing. Is there any hope for someone with debugger
- skills slightly below those of "Kon & Bal" to get the app out of SyncWait
- and make it die a clean death, or should I just restart the Mac?
- --
- Jim Walker
-
- +++++++++++++++++++++++++++
-
- >From jonasw@lysator.liu.se (Jonas Wallden)
- Date: 16 Oct 1994 09:57:15 GMT
- Organization: (none)
-
- walkerj@math.scarolina.edu (James W. Walker) writes:
-
- >When an application freezes, dropping into MacsBug often reveals that it
- >is stuck in SyncWait. When that happens, typing es to MacsBug or using
- >force-quit does nothing. Is there any hope for someone with debugger
- >skills slightly below those of "Kon & Bal" to get the app out of SyncWait
- >and make it die a clean death, or should I just restart the Mac?
- >--
- > Jim Walker
-
- The SyncWait loop waits for a parameter block error code to drop below +1
- (which is the value used while the call is in progress), and as we all know
- this error code is 0 (noErr) for a successful request and negative for
- errors.
-
- So, look at the SyncWait code to see which word it tests (usually something
- like 10(A0)) and set this word to an error code (e.g. FFD5 for fileNotFound)
- and it will often get you out of the lock.
-
- I've used it successfully in Mosaic several times where it seems to hang
- when I abort a connection, and at other times when the computer won't
- reboot after a crash.
-
- BTW, I have a MacsBug dcmd which lists error strings from error codes.
- This is great as it's rather difficult to use ObiWan at these times...
- Can't remember if I got it from sumex or a Developer CD, though.
-
- --
- `.`. Jonas Wallden `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
- `.`.`. Internet: jonasw@lysator.liu.se `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
- `.`.`.`. AppleLink: sw1369 `.`.`.`.`.`.`.`.`.`.`.`.`.`.`.
-
- +++++++++++++++++++++++++++
-
- >From wysocki@netcom.com (Chris Wysocki)
- Date: Sun, 16 Oct 1994 16:31:58 GMT
- Organization: NETCOM On-line Communication Services (408 261-4700 guest)
-
- In article <walkerj-1510942139180001@192.0.2.1>,
- James W. Walker <walkerj@math.scarolina.edu> wrote:
-
- >When an application freezes, dropping into MacsBug often reveals that it
- >is stuck in SyncWait. When that happens, typing es to MacsBug or using
- >force-quit does nothing. Is there any hope for someone with debugger
- >skills slightly below those of "Kon & Bal" to get the app out of SyncWait
- >and make it die a clean death, or should I just restart the Mac?
-
- Here's a MacsBug dcmd that I wrote a few weeks ago that simply does a
- KillIO for a specified driver. You might be able to use this when
- you're stuck in _SyncWait to kill the pending request and get out
- safely. Since it's so small, I've attached it below, along with the
- source code to it; hope you find it useful.
-
- Chris.
-
- - ------
-
- +++++++++++++++++++++++++++
-
- >From h+@nada.kth.se (Jon W{tte)
- Date: Sun, 16 Oct 1994 20:15:31 +0100
- Organization: Royal Institute of Something or other
-
- In article <walkerj-1510942139180001@192.0.2.1>,
- walkerj@math.scarolina.edu (James W. Walker) wrote:
-
- >When an application freezes, dropping into MacsBug often reveals that it
- >is stuck in SyncWait. When that happens, typing es to MacsBug or using
- >force-quit does nothing. Is there any hope for someone with debugger
- >skills slightly below those of "Kon & Bal" to get the app out of SyncWait
- >and make it die a clean death, or should I just restart the Mac?
-
- Usually this means a SCSI request isn't being served (or an
- Ethernet request, or a Serial Port request, or...) This is
- usually caused because of buggy drivers (like early Applied
- Engineering drivers, some CD-ROM and MO drivers and version 1.x
- of the Digidesign card drivers)
-
- When something hangs in _vSyncWait, it waits for the word at
- (a0)+10 to go 0 or negative (this is ioResult in the parameter
- block) One thing you can TRY is:
-
- atba
- sw a0+10 ffff
- g
- atc
- es
-
- This will make the app halt as soon as it gets to an A-trap (so
- it won't just get stuck again) Then it fakes an interrupt
- service routine that sets the result to -1 (an error code) Run
- with this; and as soon as an A-trap is hit, clear breaks and
- exit.
-
- However, since this is a driver that got hosed, chances are
- you'll run into the same problem an instant later, so it's
- usually not terribly helpful.
-
- There are also several conditions which can make this fail:
-
- - If some idiot masked interrupts, that's the reason you're
- waiting for an interrupt that's never serviced. Check with TD
- and look at the Int= figure - should be 0. 7 is real bad.
-
- - If this was because of a file manager request; the file
- manager is now in a meeting for the rest of the day, which
- means you earned just about nothing by breaking out.
-
- - If the driver makes interesting assumptions about the return
- value you use (ffff==-1 in this case) OR wants a completion
- routine to be called, you're probably hosed anyway.
-
- There should be a law only competent people can write drivers.
- Unfortunately it seems to be the other way around with some
- people "Hey, we've got this interesting hardware we can sell.
- However, hiring someone expensive to write the drivers would
- eat into our margin way too much. Isn't Joes 13-year-old kid
- into computers? Have him whip something up and we'll give him a
- Happy Meal."
-
- Hardware without drivers is pretty useless.
-
- Cheers,
-
- / h+
-
-
- --
- Jon W$E4tte (h+@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
-
- -- I don't fear death, it's dying that scares me.
-
-
- +++++++++++++++++++++++++++
-
- >From jumplong@aol.com (Jump Long)
- Date: 17 Oct 1994 00:44:01 -0400
- Organization: America Online, Inc. (1-800-827-6364)
-
- In article <walkerj-1510942139180001@192.0.2.1>,
- walkerj@math.scarolina.edu (James W. Walker) wrote:
-
- >When an application freezes, dropping into MacsBug often reveals that it
- >is stuck in SyncWait. When that happens, typing es to MacsBug or using
- >force-quit does nothing. Is there any hope for someone with debugger
- >skills slightly below those of "Kon & Bal" to get the app out of SyncWait
- >and make it die a clean death, or should I just restart the Mac?
-
- Here are a couple of paragraphs from the article "Asynchronous Routines on
- the Macintosh" in develop issue #13 that explain deadlock conditions and
- SyncWait:
-
- - ----
-
- Avoid SyncWait.
-
- Does your Macintosh just sit there not responding to user events? Drop
- into the debugger and take a look at the code that's executing. Does it
- look like this?
-
- MOVE.W $0010(A0),D0
- BGT.S -$04,(PC)
-
- That's SyncWait, the routine that synchronous calls sit in while waiting
- for a request to complete. Register A0 points to the parameter block used
- to make the call, offset $10 is the ioResult field of the parameter block,
- and SyncWait is waiting for ioResult to be less than or equal to 0
- (noErr).
-
- The ioResult field is changed by code executing as a result of an
- interrupt. If interrupts are disabled (because the synchronous call was
- made at interrupt time) or if the synchronous call was made to a service
- that's busy, you'll be in SyncWait forever. Take a look at the parameter
- block and where it is in memory, and you'll probably be able to figure out
- which synchronous call was made at interrupt time and which program made
- it.
-
- - ---
-
- Deadlock is a state in which each of two or more processes is waiting for
- one of the other processes to release some resource necessary for its
- completion. The resource may be a file, a global variable, or even the
- CPU. The process could, for example, be an application's main event loop
- or a Time Manager task.
-
- When deadlock occurs on the Macintosh, usually at least one of the
- processes is executing as the result of an interrupt. VBL tasks, Time
- Manager tasks, Deferred Task Manager tasks, completion routines, and
- interrupt handlers can all interrupt an application's main thread of
- execution. When the interrupted process is using a resource that the
- interrupting process needs, the processes are deadlocked.
-
- For example, suppose a Time Manager task periodically writes data to a
- file by making a synchronous Write request, and an application reads the
- data from its main event loop. Depending on the frequency of the task and
- the activity level of the File Manager, the Time Manager task may often
- write successfully. Inevitably, however, the Time Manager task will
- interrupt the application's Read request and deadlock will occur.
-
- Because the File Manager processes only one request at a time, any
- subsequent requests must wait for the current request to complete. In this
- case, the synchronous request made by the Time Manager task must wait for
- the application's Read request to complete before its Write request will
- be processed. Unfortunately, the File Manager must wait for the Time
- Manager task to complete before it can resume execution. Each process is
- now waiting for the other to complete, and they will continue to wait
- forever.
-
- Synchronous requests at interrupt time tend to produce deadlock, because
- the call is queued for processing and then the CPU sits and spins, waiting
- for an interrupt to occur, which signals that the request has been
- completed. If interrupts are turned off, or if a previous pending request
- can't finish because it's waiting to resume execution after the interrupt,
- the CPU will wait patiently (and eternally) for the request to finish -
- until you yank the power cord from the wall.
-
- - ---
-
- Read the rest of that article, it'll help you write code that doesn't end
- up in SyncWait.
-
- - Jim Luther
-
-
- +++++++++++++++++++++++++++
-
- >From walkerj@math.scarolina.edu (James W. Walker)
- Date: Mon, 17 Oct 1994 23:41:46 -0500
- Organization: Dept. of Mathematics, Univ. of South Carolina
-
- In article <37sveh$t0t@newsbf01.news.aol.com>, jumplong@aol.com (Jump
- Long) wrote:
-
- > Read the rest of that article, it'll help you write code that doesn't end
- > up in SyncWait.
-
- I guess I didn't make it clear in my original post, but it's not *my* code
- that gets stuck in SyncWait. It's usually Internet apps like Anarchie. I
- was just wondering whether there was anything I could do when it happens,
- other than restart, and this thread has given me some ideas. Gee, I can
- hardly wait for the next freeze. :-)
- --
- Jim Walker
-
- +++++++++++++++++++++++++++
-
- >From bierman@caelab1.cae.wisc.edu (Peter Bierman)
- Date: Tue, 18 Oct 1994 14:36:31 -0600
- Organization: Happy Frogs, Inc.
-
- In article <walkerj-1710942341460001@192.0.2.1>,
- walkerj@math.scarolina.edu (James W. Walker) wrote:
-
- > In article <37sveh$t0t@newsbf01.news.aol.com>, jumplong@aol.com (Jump
- > Long) wrote:
- >
- > > Read the rest of that article, it'll help you write code that doesn't end
- > > up in SyncWait.
- >
- > I guess I didn't make it clear in my original post, but it's not *my* code
- > that gets stuck in SyncWait. It's usually Internet apps like Anarchie. I
- > was just wondering whether there was anything I could do when it happens,
- > other than restart, and this thread has given me some ideas. Gee, I can
- > hardly wait for the next freeze. :-)
-
-
- Well, all of the ideas are good and accurate, but here's an easy fix.
-
- Do a step (oa-T) till Macsbug says "Will [not] branch". Then type:
-
- pc=pc+2
-
- g
-
- That will jump you out of the loop. It's faster than "fixing" the loop
- condition. Just note that what John said is true: it'll probobly happen
- again withing a short time. Restart right away.
-
- -Peter
-
- --
- Peter Bierman \ The Metropolis \ The most primitive part of
- the
- bierman@caelab1.cae.wisc.edu\ (614)-846-1911 \ the brain concerns itself
- \ 600MB Mac Files \ with the "Four F's":
- "I've changed my mind, Hobbes.\ FirstClass GUI \ Feeding, Fighting,
- Fleeing,
- people are scum." --Calvin \ Info-Mac CD-ROM \ and Reproduction.
-
- +++++++++++++++++++++++++++
-
- >From richardb@cocytus.demon.co.uk (Richard Buckle)
- Date: Wed, 19 Oct 1994 06:37:42 GMT
- Organization: none
-
- In article <AAC73A63966886B32@klkmac003.nada.kth.se>,
- h+@nada.kth.se (Jon W{tte) wrote:
-
- >>When an application freezes, dropping into MacsBug often reveals that it
- >>is stuck in SyncWait. When that happens, typing es to MacsBug or using
- >>force-quit does nothing. Is there any hope for someone with debugger
- >>skills slightly below those of "Kon & Bal" to get the app out of SyncWait
- >>and make it die a clean death, or should I just restart the Mac?
-
- To be honest you can often get away with stepping over the SyncWait test if
- you restart *immediately* you regain control.
-
- In MacsBug, do a T 40. This should pop you out of any subroutines you're in
- and leave you in the 2-step SyncWait loop; if not, keep doing T 40 until
- you are. If you're at the TST instruction, do one more T to get to the
- branch instruction. Then do PC=PC+2;G to exit the loop.
-
- You may need to repeat this process one or more times to regain control.
- Once you have control, go straight to the Finder and to a Restart before
- the driver can bite you again.
-
- No guarantees and YMMV. However, 90% of the tine this lets be save my work
- :-|
-
-
-
- - -----------------------------------------------------
- Richard Buckle
- richardb@cocytus.demon.co.uk
- Using this darned fine NewsHopper thingy.
-
-
- +++++++++++++++++++++++++++
-
- >From quinn@cs.uwa.edu.au (Quinn "The Eskimo!")
- Date: Fri, 28 Oct 1994 10:13:36 +0800
- Organization: Department of Computer Science, The University of Western
- Australia
-
- In article <walkerj-1710942341460001@192.0.2.1>,
- walkerj@math.scarolina.edu (James W. Walker) wrote:
-
- >I guess I didn't make it clear in my original post, but it's not *my* code
- >that gets stuck in SyncWait. It's usually Internet apps like Anarchie.
-
- For reliable program (like Anarchie :) disappearing into SyncWait normally
- means that your networking on your machine is stuffed up somehow.
-
- To get out try this in MacsBug...
-
- sm a0+10 ffff
- g
-
- What it does is set the ioResult field of the paramblock to -1, indicating
- an error. You often have to do it a *lot* of times before it comes back
- and often it doesn't work at all. But it makes you feel like you've got
- control (:
-
- Share and Enjoy.
- --
- Quinn "The Eskimo!" "I wasn't the one who fired the heat seeking
- population annihilator out the window!"
- Amaze your friends! Learn some cool MacsBug or MicroBug commands today (:
-
- +++++++++++++++++++++++++++
-
- >From devon_hubbard@taligent.com (Devon Hubbard)
- Date: Fri, 28 Oct 1994 16:20:48 GMT
- Organization: Taligent, Inc.
-
- In article <quinn-2810941013360001@mac168.cs.uwa.oz.au>,
- quinn@cs.uwa.edu.au (Quinn "The Eskimo!") wrote:
-
- >In article <walkerj-1710942341460001@192.0.2.1>,
- >walkerj@math.scarolina.edu (James W. Walker) wrote:
- >
- >>I guess I didn't make it clear in my original post, but it's not *my* code
- >>that gets stuck in SyncWait. It's usually Internet apps like Anarchie.
- >
- >For reliable program (like Anarchie :) disappearing into SyncWait normally
- >means that your networking on your machine is stuffed up somehow.
- >
- >To get out try this in MacsBug...
- >
- > sm a0+10 ffff
- > g
- >
- >What it does is set the ioResult field of the paramblock to -1, indicating
- >an error. You often have to do it a *lot* of times before it comes back
- >and often it doesn't work at all. But it makes you feel like you've got
- >control (:
-
- Ouch! OUCH! This is assuming that reg A0 really points to the
- cntrlParamBlockRec, which I hate to say doesn't always! I recently ran
- into a vSyncWait problem (on an 8100av) that lead to fingering the
- offending driver by looking at the data moved off D2 and matching that as
- a DCE entry with the help of Macsbug's 'drvr' dcmd. In every case of
- vSyncWait hang, a0 WAS NOT pointing to a valid paramblock so do a
-
- dm a0 cntrlparamblockrec
-
- before the 'sm' and make sure it looks like a valid paramblock, or you'll
- surely be rebooting thereafter.
-
- dEVoN
-
- - -----------------------------------------------------------------------
- Devon Hubbard Silicon Pilot
- devon_hubbard@taligent.com Taligent, Inc
-
- ---------------------------
-
- >From macrshap@bbn.com (Richard Shapiro)
- Subject: having trouble with AEInteractWithUser & drag manager
- Date: 9 Oct 1994 17:09:27 GMT
- Organization: Bolt, Beranek and Newman Inc.
-
- I'm in the process of adding some drag-support to an application. It's
- working ok when the application is selected, so the underlying drag
- management seems fine. But usually, I want to drag when another
- application is selected (ie I'll be dragging from that other application).
- In this case, when my app receives the drag, it needs to interact with the
- user before proceeding. This is where I'm stuck.
-
- I've set the InteractionAllowed flag to kAEInteractWithLocal (the default,
- I know, but I thought I'd be explicit), and I carefully call
- AEInteractWithUser before attempting any interaction. I'm calling it
- without a timeout (kNoTimeOut), without a notification rec (should be OK
- since I have the relevant BNDL, FREF and ICN# resources defined), and with
- a very simple idle procedure which essentially does nothing (since at the
- moment nothing in my app cares about update or activate events).
-
- What I expected to happen was the usual flashing in the
- current-application icon (on the right edge of the menubar), which would
- allow me to bring my app to the front. What actually happens is...nothing:
- no flashing, no process paying attention to mouse clicks, hence no way to
- select my application (which has received the drop and is waiting in the
- call to AEInteractWithUser) so that I can interact with it. All I can do
- is cmd-opt-escape to force a quit.
-
- What am I doing wrong? I'm assuming it must be one of two things: either
- it's illegal to have user interaction after receiving a drop but before
- acknowledging receipt; or I need to handle something in my idle function
- which I'm not currently handling.
-
- Any suggestions? If it matters, I'm using CW 4.5 C, and running System 7.1
- on a q660av with drag extensions and the drag-ware Finder (7.1.3). The
- drag flavors I'm handling at the moment are 'hfs ' and 'TEXT'.
-
- Please copy followups to email -- thanks.
-
- --
- rs/macrshap@bbn.com
-
- +++++++++++++++++++++++++++
-
- >From Jens Alfke <jens_alfke@powertalk.apple.com>
- Date: Mon, 10 Oct 1994 22:12:55 GMT
- Organization: Apple Computer
-
- Richard Shapiro, macrshap@bbn.com writes:
- > What am I doing wrong? I'm assuming it must be one of two things: either
- > it's illegal to have user interaction after receiving a drop but before
- > acknowledging receipt
-
- Bingo -- more specifically, it's illegal to cause a process switch while
- inside a drag handler, since the drag handlers are called via a lightweight
- process switch that is not compatible with the regular kind of process
- switch. While you're in a drag handler, WNE is hacked to do nothing for
- compatibility, but other ways to interact (such as calling AEInteractWithUser
- or SetFrontProcess) will choke your machine.
-
- Moral: Wait until after the drag finishes to try to interact with the user.
-
- --Jens Alfke jens_alfke@powertalk.apple.com
- "A man, a plan, a yam, a can of Spam ... Bananama!"
-
- +++++++++++++++++++++++++++
-
- >From macrshap@bbn.com (Richard Shapiro)
- Date: 11 Oct 1994 01:54:10 GMT
- Organization: Bolt, Beranek and Newman Inc.
-
- In article <1994Oct10.221255.26429@gallant.apple.com>, Jens Alfke
- <jens_alfke@powertalk.apple.com> wrote:
-
- > Bingo -- more specifically, it's illegal to cause a process switch while
- > inside a drag handler, since the drag handlers are called via a lightweight
- > process switch that is not compatible with the regular kind of process
- > switch. While you're in a drag handler, WNE is hacked to do nothing for
- > compatibility, but other ways to interact (such as calling
- AEInteractWithUser
- > or SetFrontProcess) will choke your machine.
- >
- > Moral: Wait until after the drag finishes to try to interact with the user.
-
- OK, I eventually came to that conclusion myself. I guess it's good to have
- it validated...
-
- Problem is, I really need user interaction to complete the processing of
- the drop. So, I tried to get around it by stashing the DragReference in a
- global, setting a flag, returning from the handler, and then dealing with
- the stashed DragReference when I'm back in the main event loop (depending
- on the flag, of course). This doesn't work either. I can interact with the
- user, but it looks as though the information associated with the
- DragReference vanishes once the handler is exited. At least, I can't get
- CountDragItems and the like to work properly outside the handler context.
- Are these supposed to work outside the handler?
-
- That seems to leave me with one final option: I have to get *all* the data
- out of the DragReference while I'm in the handler, stash the whole pile
- somewhere, exit the handler, and process the data later. Yucch, that's
- pretty awful. Is there another possibility I'm missing here?
-
- For now, I "fixed" the application to run without user-interaction when it
- isn't in the foreground (which can only happen as a result of a drop).
- It's better than nothing, but really not what I want...
-
- --
- rs/macrshap@bbn.com
-
- +++++++++++++++++++++++++++
-
- >From Jens Alfke <jens_alfke@powertalk.apple.com>
- Date: Tue, 11 Oct 1994 17:28:36 GMT
- Organization: Apple Computer
-
- Richard Shapiro, macrshap@bbn.com writes:
- > That seems to leave me with one final option: I have to get *all* the data
- > out of the DragReference while I'm in the handler, stash the whole pile
- > somewhere, exit the handler, and process the data later. Yucch, that's
- > pretty awful. Is there another possibility I'm missing here?
-
- Since you can't possibly use the DragReference after the sender disposes of
- it, I think this is your only option. Is it that bad? Get the data you want
- to use, stash it somewhere temporary, and when you get back into your event
- loop ask the user what to do with it.
-
- --Jens Alfke jens_alfke@powertalk.apple.com
- "A man, a plan, a yam, a can of Spam ... Bananama!"
-
- +++++++++++++++++++++++++++
-
- >From macrshap@bbn.com (Richard Shapiro)
- Date: 11 Oct 1994 22:25:03 GMT
- Organization: Bolt, Beranek and Newman Inc.
-
- In article <1994Oct11.172836.17257@gallant.apple.com>, Jens Alfke
- <jens_alfke@powertalk.apple.com> wrote:
-
-
- > Since you can't possibly use the DragReference after the sender disposes of
- > it
-
- As expected.
-
- > I think this is your only option. Is it that bad? Get the data you want
- > to use, stash it somewhere temporary, and when you get back into your event
- > loop ask the user what to do with it.
-
- No, it's not as bad as I thought. In fact it's already done and the result
- is cleaner than my original plan :)
-
- Now on to my next drag-manager question: receiving promise-hfs drags in an
- application other than the Finder. Details in another posting...
-
- --
- rs/macrshap@bbn.com
-
- +++++++++++++++++++++++++++
-
- >From leonardr@netcom.com (Leonard Rosenthol)
- Date: Wed, 19 Oct 1994 22:01:35 GMT
- Organization: Aladdin Systems, Inc.
-
- In article <macrshap-1110941825500001@ipa.bbn.com>, macrshap@bbn.com
- (Richard Shapiro) wrote:
-
- > > I think this is your only option. Is it that bad? Get the data you want
- > > to use, stash it somewhere temporary, and when you get back into your
- event
- > > loop ask the user what to do with it.
- >
- > No, it's not as bad as I thought. In fact it's already done and the result
- > is cleaner than my original plan :)
- >
- What I've been doing in this case is to get all the info from the Drag,
- and then send it back to myself in an Apple event (but NOT in sendToSelf
- mode). This works quite nicely...
-
-
- Leonard
- - ------------------------------------------------------------------------
- Leonard Rosenthol Internet: leonardr@netcom.com
- Director of Advanced Technology AppleLink: MACgician
- Aladdin Systems, Inc. GEnie: MACgician
-
- +++++++++++++++++++++++++++
-
- >From jonpugh@netcom.com (Jon Pugh)
- Date: Wed, 26 Oct 1994 07:08:53 GMT
- Organization: Will hack for food
-
- Leonard Rosenthol (leonardr@netcom.com) wrote:
- > What I've been doing in this case is to get all the info from the Drag,
- > and then send it back to myself in an Apple event (but NOT in sendToSelf
- > mode). This works quite nicely...
-
- I actually send the event twice. Once to myself as record only, and then
- again with signature addressing so that it goes through the event loop.
- That way you can record the event too.
-
- Jon
-
-
- ---------------------------
-
- End of C.S.M.P. Digest
- **********************
-
-
- ---------------------------------------------------------------------
-
- NOTE: The following Macintosh file(s) are enclosed with this
- message, in BinHex format. If your mail system does not convert
- BinHex files automatically, you will need to transfer the message to
- a Mac and run the BinHex application to decode it.
-
- Filename: KillIO dcmd.sit Size: 3181 bytes
-
- ---------------------------------------------------------------------
-
- (This file must be converted with BinHex 4.0)
-
-
-